package com.infore.dataAudit.service.impl;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipInputStream;

import javax.annotation.Resource;

import org.activiti.bpmn.model.BpmnModel;
import org.activiti.editor.constants.ModelDataJsonConstants;
import org.activiti.editor.language.json.converter.BpmnJsonConverter;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.Model;
import org.activiti.engine.repository.ProcessDefinition;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.infore.dataAudit.conf.ProcessDeployAutoSettings;
import com.infore.dataAudit.dto.HourData;
import com.infore.dataAudit.dto.Project;
import com.infore.dataAudit.dto.SpanDrift;
import com.infore.dataAudit.dto.ZeroDrift;
import com.infore.dataAudit.enums.AirAuditUsers;
import com.infore.dataAudit.enums.ResultStatus;
import com.infore.dataAudit.remote.IBaseDataService;
import com.infore.dataAudit.remote.IQualityControlService;
import com.infore.dataAudit.remote.IReceiveDataService;
import com.infore.dataAudit.remote.IStatisticsAndAlarm;
import com.infore.dataAudit.service.DeployService;
import com.infore.dataAudit.service.RunningTimeService;
import com.infore.dataAudit.util.Constants;
import com.infore.dataAudit.util.ObjectMapperUtil;
import com.infore.dataAudit.util.ResultEntity;
import com.infore.dataAudit.vo.QualityParamOutSelectBo;

/**
 * deploy服务层
 * 
 * @author cys
 *
 */
@Service("deployService")
public class DeployServiceImpl implements DeployService {

	@Resource
	private RepositoryService repositoryService;
	@Resource
	private ObjectMapper objectMapper;

	@Resource
	private RunningTimeService runningTimeService;
	@Autowired
	private IReceiveDataService receiveDataService;
	@Autowired
	private IQualityControlService qualityControlService;
	@Autowired
	private IBaseDataService baseDataService;
	@Autowired
	private ObjectMapperUtil objectMapperUtil;
	@Autowired
	private IBaseDataService iBaseDataService;
	@Autowired
	private ProcessDeployAutoSettings processDeployAutoSettings;
	@Autowired
	IStatisticsAndAlarm statisticsAndAlarm;

	@Override
	public ResultEntity addDeploy(MultipartFile deployFile) throws IOException {
		if (deployFile == null) {
			return null;
		}
		Deployment deploy = repositoryService.createDeployment() // 创建部署
				.name(deployFile.getOriginalFilename()) // 需要部署流程名称
				.addZipInputStream(new ZipInputStream(deployFile.getInputStream()))// 添加ZIP输入流
				.deploy(); // 开始部署
		if (deploy != null) {
			ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
					.deploymentId(deploy.getId()).singleResult();
			BpmnModel model = repositoryService.getBpmnModel(processDefinition.getId());
			BpmnJsonConverter converter = new BpmnJsonConverter();
			ObjectNode modelNode = converter.convertToJson(model);
			Model modelData = repositoryService.newModel();
			ObjectNode modelObjectNode = objectMapper.createObjectNode();

			modelObjectNode.put(ModelDataJsonConstants.MODEL_NAME, processDefinition.getName());
			modelObjectNode.put(ModelDataJsonConstants.MODEL_REVISION, processDefinition.getVersion());
			modelObjectNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, processDefinition.getDescription());
			modelData.setMetaInfo(modelObjectNode.toString());
			modelData.setName(processDefinition.getName());
			modelData.setKey(processDefinition.getKey());
			modelData.setVersion(processDefinition.getVersion());
			modelData.setTenantId(processDefinition.getTenantId());

			repositoryService.saveModel(modelData);
			repositoryService.addModelEditorSource(modelData.getId(), modelNode.toString().getBytes("utf-8"));

			return new ResultEntity(ResultStatus.SUCCESS, "部署成功");
		}
		return new ResultEntity(ResultStatus.ERROR, "部署流程失败");
	}

	@Override
	public ResultEntity delDeploy(String fileNames) {
		if (fileNames == null || fileNames.trim().isEmpty()) {
			return new ResultEntity(ResultStatus.ERROR, "参数错误!");
		}
		String[] names = fileNames.split(",");

		for (String name : names) {
			repositoryService.deleteDeployment(name.trim(), true);
		}
		return new ResultEntity(ResultStatus.SUCCESS, "删除成功");
	}

	@Override
	public Map<String, Object> queryDeployByPage(String deployName, Integer pageSize, Integer page) {
		long count = repositoryService.createDeploymentQuery().deploymentNameLike("%" + deployName + "%").count();
		Map<String, Object> resultmap = new HashMap<String, Object>();
		if (count != 0L) {
			List<Deployment> deployList = repositoryService.createDeploymentQuery()// 创建流程查询实例
					.orderByDeploymenTime().desc() // 降序
					.deploymentNameLike("%" + deployName + "%") // 根据Name模糊查询
					.listPage(page, pageSize);
			resultmap.put("rows", deployList);
		} else {
			resultmap.put("rows", null);
		}
		resultmap.put("total", count);
		return resultmap;
	}

	// zdTime 指定审核某天数据 否则查询当前一天与前两天的数据
	@Override
	public void startAuditFlow(String zdTime, String siteMn) {
		// 1 获取前一天的0点开始23点 站点数据 过滤只要监测站数据 监测站mn
		Calendar calendar = Calendar.getInstance();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		String quTimeEnd = sdf.format(calendar.getTime());
		calendar.add(Calendar.DAY_OF_MONTH, -1);
		String time = sdf.format(calendar.getTime());
		int dt = calendar.get(Calendar.DAY_OF_MONTH);
		// 当天下午四点自动完成 为人工完成的话
		String oneTimeEnd = this.getOneTimeEnd();
		// oneTimeEnd = "2019-04-24T12:00:11";
		// 下个月7号
		System.out.println("任务调度开始-------------");
		System.out.println("自定时间补传审核-------------" + zdTime);
		// time = "2019-06-09";
		if (zdTime != null) {
			time = zdTime;
		}
		String oneTimeEnd2 = this.getOneTimeEnd2();
		// oneTimeEnd2 = "2019-05-23T14:50:11";
		List<String> mnList = new ArrayList<>();
		// 查询站点监测小时数据
		calendar.add(Calendar.DAY_OF_MONTH, -1);
		String timePre = sdf.format(calendar.getTime());
		if (zdTime != null) {
			timePre = zdTime;
		}
		ResultEntity re = receiveDataService.queryHourData(timePre + " 00:00:00", time + " 23:59:59");
//		ResultEntity re = receiveDataService.queryHourData("2020-11-12 00:00:00", "2020-11-12 23:59:59");
		List<HourData> HourDatas = objectMapperUtil.convertList(re, HourData.class);
		Map<String, List<HourData>> mapHourData = new HashMap<>();
		Map<String, List<HourData>> mapHourDataPre = new HashMap<>();// 前一天用于质控无效设置的数据
		for (HourData hourData : HourDatas) {
			String mn = hourData.getMn();
			if (StringUtils.isNotBlank(siteMn) && !siteMn.equals(mn)) {// 如果单传站点，只补发一个站点数据
				continue;
			}
			Date t = hourData.getDataTime();
			if (t == null)
				continue;
			calendar.setTime(t);
			int day = calendar.get(Calendar.DAY_OF_MONTH);
			if (day == dt || zdTime != null) {
				if (mapHourData.get(mn) == null) {
					mnList.add(mn);
					mapHourData.put(mn, new ArrayList<>());
				}
				mapHourData.get(mn).add(hourData);
			} else {
				if (mapHourDataPre.get(mn) == null) {
					// mnList.add(mn);
					mapHourDataPre.put(mn, new ArrayList<>());
				}
				mapHourDataPre.get(mn).add(hourData);
			}
		}
		// 用于自动审核
		Constants.setStationHourData(mapHourData);
		Constants.setStationHourDataPre(mapHourDataPre);
		// 查询日零点
		QualityParamOutSelectBo qualityParamSelectBo = new QualityParamOutSelectBo();
		List<String> indexCodes = this.getIndexCodes();
		qualityParamSelectBo.setStartTime(time + " 00:00:00");
		qualityParamSelectBo.setEndTime(quTimeEnd + " 23:00:00");
		qualityParamSelectBo.setStationCodes(mnList);
		qualityParamSelectBo.setIndexCodes(indexCodes);
		ResultEntity zeroRe = qualityControlService.zeroDriftData(qualityParamSelectBo);
		ResultEntity spanRe = qualityControlService.spanDriftData(qualityParamSelectBo);
		// 零点数据 存储值静态变量中
		this.setZeroDriftData(zeroRe);
		// 跨度数据 存储值静态变量中
		this.setSpanDriftData(spanRe);
		// System.out.println(Constants.getStationSpanDrift());
		// System.out.println(Constants.getStationZeroDrift());
		// String[] stationMns = {};
		Map<String, Object> params = null;
		for (String mn : mnList) {
			params = new HashMap<>();
//            params.put("userId1", "熊律欣");
//            params.put("userId2", "武云霞");
//            params.put("userId3", "卢凤媛");
			params.put("userId1", AirAuditUsers.YW.getStatusCode());
			params.put("userId2", AirAuditUsers.XZ.getStatusCode());
			params.put("userId3", AirAuditUsers.SQ.getStatusCode());
			params.put("stationMn", mn);
			params.put("stationTime", time);
			params.put("oneTimeEnd", oneTimeEnd);
			params.put("oneTimeEnd2", oneTimeEnd2);
			runningTimeService.startProcess(processDeployAutoSettings.getDataAuditKey(), params);
		}
		// ResultEntity result = runningTimeService.startProcess("audioFlow01", null);
		// log.info("数据审核开启--The time is now {}",result.getContent() +"--"+
		// dateFormat.format(new Date()));
	}

	@Override
	public void startAirAuditFlow(String zdTime) {
		// 1 获取前一天的0点开始23点 站点数据 过滤只要监测站数据 监测站mn
		Calendar calendar = Calendar.getInstance();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		String quTimeEnd = sdf.format(calendar.getTime());
		calendar.add(Calendar.DAY_OF_MONTH, -1);
		String time = sdf.format(calendar.getTime());
		// 当天下午四点自动完成 为人工完成的话
		String oneTimeEnd = this.getOneTimeEnd();
		// oneTimeEnd = "2019-04-24T12:00:11";
		// 下个月7号
		System.out.println("任务调度开始 空气站审核-------------");
		System.out.println("自定时间补传审核-------------" + zdTime);
		// time = "2019-06-09";
		if (zdTime != null) {
			time = zdTime;
		}
		String oneTimeEnd2 = this.getOneTimeEnd2();
		// oneTimeEnd2 = "2019-05-23T14:50:11";
		List<String> mnList = new ArrayList<>();
		// 查询站点监测小时数据 查询两天的数据 当天的数据做数据审核 前天的数据用于质控数据无效判断更新（质控无效时前一天24小时无效）。
		ResultEntity re = statisticsAndAlarm.queryHourDataAirByTime(time + " 00:00:00", time + " 23:59:59");
		List<HourData> HourDatas = objectMapperUtil.convertList(re, HourData.class);
		Map<String, List<HourData>> mapHourData = new HashMap<>();// 当天审核的数据
		for (HourData hourData : HourDatas) {
			String mn = hourData.getMn();
			Date t = hourData.getDataTime();
			if (t == null)
				continue;
			if (mapHourData.get(mn) == null) {
				mnList.add(mn);
				mapHourData.put(mn, new ArrayList<>());
			}
			mapHourData.get(mn).add(hourData);
		}
		// 用于自动审核
		Constants.setStationHourData(mapHourData);
		// 查询日零点 空气取消质控判断
//        QualityParamOutSelectBo qualityParamSelectBo = new QualityParamOutSelectBo();
//        List<String> indexCodes = this.getIndexCodes();
//        qualityParamSelectBo.setStartTime(time + " 00:00:00");
//        qualityParamSelectBo.setEndTime(quTimeEnd + " 23:00:00");
//        qualityParamSelectBo.setStationCodes(mnList);
//        qualityParamSelectBo.setIndexCodes(indexCodes);
//        ResultEntity zeroRe =  qualityControlService.zeroDriftData(qualityParamSelectBo);
//        ResultEntity spanRe =  qualityControlService.spanDriftData(qualityParamSelectBo);
		// 零点数据 存储值静态变量中
		this.setZeroDriftData(null);
		// 跨度数据 存储值静态变量中
		this.setSpanDriftData(null);
		// System.out.println(Constants.getStationSpanDrift());
		// System.out.println(Constants.getStationZeroDrift());
		// String[] stationMns = {};
		Map<String, Object> params = null;
		// 空气站通州默认写死 先
		for (String mn : mnList) {
			params = new HashMap<>();
			params.put("userId1", AirAuditUsers.YW.getStatusCode());
			params.put("userId2", AirAuditUsers.XZ.getStatusCode());
			params.put("userId3", AirAuditUsers.SQ.getStatusCode());
			params.put("stationMn", mn);
			params.put("stationTime", time);
			params.put("oneTimeEnd", oneTimeEnd);
			params.put("oneTimeEnd2", oneTimeEnd2);
			runningTimeService.startProcess(processDeployAutoSettings.getDataAuditKey(), params);
		}
		// ResultEntity result = runningTimeService.startProcess("audioFlow01", null);
		// log.info("数据审核开启--The time is now {}",result.getContent() +"--"+
		// dateFormat.format(new Date()));
	}

	private List<String> getIndexCodes() {
		List<String> indexCodes = new ArrayList<>();
		ResultEntity re = baseDataService.projectInfoAllAudit();
		List<Project> ProjectList = objectMapperUtil.convertList(re, Project.class);
		for (Project project : ProjectList) {
			indexCodes.add(project.getProjectCode());
		}
		return indexCodes;
	}

	private void setSpanDriftData(ResultEntity spanRe) {
		List<SpanDrift> zeroDriftDatas = objectMapperUtil.convertList(spanRe, SpanDrift.class);
		Map<String, List<SpanDrift>> map = new HashMap<>();
		Constants.setStationSpanDrift(map);
		String mn = null;
		for (SpanDrift spanDrift : zeroDriftDatas) {
			mn = spanDrift.getStationCode();
			if (map.get(mn) == null) {
				map.put(mn, new ArrayList<>());
			}
			map.get(mn).add(spanDrift);
		}
	}

	private void setZeroDriftData(ResultEntity zeroRe) {
		List<ZeroDrift> zeroDriftDatas = objectMapperUtil.convertList(zeroRe, ZeroDrift.class);
		Map<String, List<ZeroDrift>> map = new HashMap<>();
		Constants.setStationZeroDrift(map);
		String mn = null;
		for (ZeroDrift zeroDrift : zeroDriftDatas) {
			mn = zeroDrift.getStationCode();
			if (map.get(mn) == null) {
				map.put(mn, new ArrayList<>());
			}
			map.get(mn).add(zeroDrift);
		}
	}

	/**
	 * 获取一级人工审核时间限制点 第二天16点修改成 超时完成任务 16点
	 * 
	 * @author 蔡永顺
	 * @return String
	 * @return
	 * @date 2019年4月24日下午6:52:57
	 */
	private String getOneTimeEnd() {
		Calendar c = Calendar.getInstance();
		c.set(Calendar.DAY_OF_MONTH, 1);
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		String time = sdf.format(c.getTime()) + "T16:00:00";
		return time;
	}

	/**
	 * 获取二级人工审核 省级审核 下个月7号
	 * 
	 * @author 蔡永顺
	 * @return String
	 * @return
	 * @date 2019年4月24日下午6:54:19
	 */
	private String getOneTimeEnd2() {
		Calendar calendar = Calendar.getInstance();
		calendar.add(Calendar.MONTH, 1);
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
		String time = sdf.format(calendar.getTime()) + "-07T00:00:00";
		return time;
	}

}
